#include "fileutils.h"

#include <QDir>
#include <QDebug>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonParseError>

FileUtils::~FileUtils()
{
}

// 文件最大数量
const int MAX_RECENT_FILES = 10;

QVector<QPair<QString, int>> FileUtils::importDict(const QString &filePath, EncryptMode mode, const QString &key)
{
	QVector<QPair<QString, int>> words;
	QString crossPath = getCrossPlatformPath(filePath);
	// check 
	if (!QFile::exists(crossPath) || !checkFilePermission(crossPath, true, false)) {
		qWarning() << "[FileUtils] 导入失败：文件不存在或无读权限" << crossPath;
        return words;
	}
	// read 解密
	QByteArray content = readEncryptedFile(crossPath, mode, key);
	if (content.isEmpty()) {
		qWarning() << "[FileUtils] 导入失败：内容为空或解密失败" << crossPath;
        return words;
	}
	// json反序列化
	words = deserializeFromJson(content);
    qDebug() << "[FileUtils] 导入成功：" << crossPath << "，词数量：" << words.size();
    return words;
}

bool FileUtils::exportDict(const QVector<QPair<QString, int>> &words, const QString &filePath, EncryptMode mode, const QString &key)
{
	// 导出
	if (words.isEmpty()) {
		qWarning() << "[FileUtils] 导出失败：词列表为空";
        return false;
	}
	QString crossPath = getCrossPlatformPath(filePath);
    QDir parentDir = QFileInfo(crossPath).dir();
    if (!parentDir.exists() && !parentDir.mkpath(".")) {
        qWarning() << "[FileUtils] 导出失败：无法创建目录" << parentDir.path();
        return false;
    }
	// json 序列化
	QByteArray content = serializeToJson(words);
	if (content.isEmpty()) {
		qWarning() << "[FileUtils] 导出失败：JSON序列化失败";
        return false;
	}
	// 加密write 
	// qDebug 
	bool success = writeEncryptedFile(crossPath, content, mode, key);
	if (success) {
		qDebug() << "[FileUtils] 导出成功：" << crossPath << "，词数量：" << words.size();
        addRecentFile(crossPath);
	} else 	qWarning() << "[FileUtils] 导出失败：写入或加密失败" << crossPath;
	return success;
}

QByteArray FileUtils::readEncryptedFile(const QString &filePath, EncryptMode mode, const QString &key)
{
	// 读写加密文件 
	QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        qWarning() << "[FileUtils] 读取失败：无法打开文件" << filePath << file.errorString();
        return {};
    }

    QByteArray fileData = file.readAll();
    file.close();

    if (mode == NoEncrypt) {
        return fileData; // 明文直接返回
    }

    // AES-256-CBC解密（复用EncryptUtil）
    if (mode == Aes256Encrypt) {
        QByteArray aesKey = getEncryptionKey(key);
        QString decryptedStr = EncryptUtil::decryptString(fileData, aesKey);
        return decryptedStr.toUtf8();
    }

    qWarning() << "[FileUtils] 不支持的加密模式";
    return {};
}

bool FileUtils::writeEncryptedFile(const QString &filePath, const QByteArray &content, EncryptMode mode, const QString &key)
{
	QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
        qWarning() << "[FileUtils] 写入失败：无法打开文件" << filePath << file.errorString();
        return false;
    }

    QByteArray writeData;
    if (mode == Aes256Encrypt) {
        // AES-256-CBC加密（复用EncryptUtil，自动生成IV并拼接）
        QByteArray aesKey = getEncryptionKey(key);
        writeData = EncryptUtil::encryptString(QString::fromUtf8(content), aesKey);
    } else {
        writeData = content; // 明文写入
    }

    qint64 written = file.write(writeData);
    file.close();
    return written == writeData.size();
}

bool FileUtils::checkFilePermission(const QString &filePath, bool needRead, bool needWrite)
{
	QFileInfo fileInfo(filePath);
	bool hasRead = true, hasWrite = true;

	if (fileInfo.exists()) {
		hasRead = fileInfo.isReadable();
		hasWrite = fileInfo.isWritable();
	} else {
		// check parent 权限
		QDir parentDir = fileInfo.dir();
		QFileInfo dirInfo(parentDir.absolutePath());
		hasRead = dirInfo.isReadable();
		hasWrite = dirInfo.isWritable();
	}
	// 考虑调用者请求的权限需求
	if (needRead && !hasRead) return false;
	if (needWrite && !hasWrite) return false;
	return (needRead ? hasRead : true) && (needWrite ? hasWrite : true);
}

QString FileUtils::getCrossPlatformPath(const QString &rawPath)
{
	return QDir::fromNativeSeparators(rawPath);
}

// file record
void FileUtils::addRecentFile(const QString &filePath)
{
	QSettings& settings = getSettings();
    QVector<QString> recentFiles = getRecentFiles();
	// 去重 sort
	recentFiles.removeAll(filePath);
	recentFiles.prepend(filePath);
	if (recentFiles.size() > MAX_RECENT_FILES)	recentFiles.resize(MAX_RECENT_FILES);

	settings.setValue("RecentFiles/List", QVariant::fromValue(recentFiles));
    settings.sync();
}

QVector<QString> FileUtils::getRecentFiles()
{
	return getSettings().value("RecentFiles/List").value<QVector<QString>>();
}

/// @brief helper  复用EncryptUtil的密钥生成逻辑（结合密码+设备标识，SHA-256哈希）
/// @param key 
/// @return 
QByteArray FileUtils::getEncryptionKey(const QString &key)
{
	if (key.isEmpty())	return EncryptUtil::generateKey();
	else 				return EncryptUtil::generateKey(key);
}

QByteArray FileUtils::serializeToJson(const QVector<QPair<QString, int>> &words)
{
	// json 数组
	QJsonArray jsonArray;
	for (const auto& pair : words) {
		// 对象里面去拿键值对
		QJsonObject obj;
		obj["word"] = pair.first;
		obj["freq"] = pair.second;
		jsonArray.append(obj);
	}
	return QJsonDocument(jsonArray).toJson(QJsonDocument::Compact);
}

QVector<QPair<QString, int>> FileUtils::deserializeFromJson(const QByteArray &jsonData)
{
	// 解析json
	QVector<QPair<QString, int>> words;
	QJsonParseError error;
	QJsonDocument doc = QJsonDocument::fromJson(jsonData, &error);

	if (error.error != QJsonParseError::NoError) {
		qWarning() << "[FileUtils] JSON解析失败：" << error.errorString();
        return words;
	}
	if (!doc.isArray()) {
		qWarning() << "[FileUtils] JSON格式错误（非数组）";
        return words;
	}

	QJsonArray array = doc.array();
	for (const QJsonValue& val : array) {
		if (!val.isObject())	continue;
		QJsonObject obj = val.toObject();
		
		QString word = obj["word"].toString().trimmed();
		int freq = obj["freq"].toInt();
		if (!word.isEmpty() && freq > 0)	words.append({word, freq});
	}
	return words;
}

QSettings &FileUtils::getSettings()
{
	// TODO: 在此处插入 return 语句
	static QSettings s_settings("SmartInput", "FileUtils");
	return s_settings;
}
